package org.example.crypto.core;

import lombok.RequiredArgsConstructor;
import org.example.common.util.JsonUtil;
import org.example.crypto.bean.CryptoInfoBean;
import org.example.crypto.config.ApiCryptoProperties;
import org.example.crypto.decrypt.ApiDecrypt;
import org.example.crypto.util.ApiCryptoUtil;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import java.lang.reflect.Parameter;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
 * @program: rabbitmq-study
 * @description: param 参数解析
 * @Version V1.0.0
 * @author: dazhi
 * @create: 2021-02-09 10:14
 **/
@RequiredArgsConstructor

public class ApiDecryptParamResolver implements HandlerMethodArgumentResolver {
    private final ApiCryptoProperties properties;

    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return AnnotatedElementUtils.hasAnnotation(methodParameter.getParameter(), ApiDecrypt.class);
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        Parameter parameter = methodParameter.getParameter();
        ApiDecrypt apiDecrypt = AnnotatedElementUtils.getMergedAnnotation(parameter, ApiDecrypt.class);
        String text = nativeWebRequest.getParameter(properties.getParamName());
        if (StringUtils.isEmpty(text)) {
            return null;
        }
        CryptoInfoBean infoBean = new CryptoInfoBean(apiDecrypt.value(), apiDecrypt.secretKey());
        byte[] textBytes = text.getBytes(StandardCharsets.UTF_8);
        byte[] decryptData = ApiCryptoUtil.decryptData(properties, textBytes, infoBean);
        return JsonUtil.readValue(decryptData, parameter.getType());
    }
}
